#ifndef _PACMANCLONE_H_
#define _PACMANCLONE_H_
/*
 *	PacManClone.h
 *
 *	Pac Man Clone. La duh!
 *
 *	Coded by Joseph A. Marrero
 *	1/20/2008
 */
#include <cassert>
#include <string>
#include <ImageIO.h>
#include <vector>
#include <fmod.hpp>
#include "Object.h"
#include "PacMan.h"
#include "Block.h"
#include "Empty.h"
using namespace std;

#define ESC			27

#define ERRCHECK(result)	(assert( result == FMOD_RESULT::FMOD_OK ))

void initialize( );
void deinitialize( );

void render( );
void resize( int width, int height );
void keyboard_keypress( unsigned char key, int x, int y );
void keyboard_special_keypress( int key, int x, int y );
void idle( );
void writeText( void *font, std::string &text, int x, int y, float r = 0.0f, float g = 0.0f, float b = 0.0f );
void update( int n );

extern unsigned int gWidth, gHeight;




class Ghost;

// Pac Man Game stuff
namespace Game 
{
	static const unsigned int RESOLUTION_WIDTH = 1024;
	static const unsigned int RESOLUTION_HEIGHT = 768;
	static const unsigned int FRAMES_PER_SECOND = 60;
	static const unsigned int MILLESECONDS_PER_FRAME = (1.0 / FRAMES_PER_SECOND) * 1000;
	static const float ASPECT_RATIO = ((float)RESOLUTION_WIDTH / ((float)RESOLUTION_HEIGHT));
	static const unsigned int GAME_BOARD_SIZE = 21;
	static const unsigned int HUD_WIDTH = 257;
	static const unsigned int HUD_HEIGHT = 770;
	static const unsigned int TEXTURE_SIZE = 21;
	static const float BLOCK_WIDTH = (RESOLUTION_WIDTH - HUD_WIDTH) / ((float) GAME_BOARD_SIZE);
	static const float BLOCK_HEIGHT = (RESOLUTION_HEIGHT) / ((float) GAME_BOARD_SIZE);
	static const unsigned int UPDATE_FREQUENCY = 100;
	static const unsigned int NUMBER_OF_LEVELS = 4;
	
	static const unsigned int SMALL_DOT_POINTS = 1;
	static const unsigned int BIG_DOT_POINTS = 5;

	extern ImageIO::Image tgaBlockImage[ 7 ];
	extern ImageIO::Image tgaBigDotImage;
	extern ImageIO::Image tgaSmallDotImage;
	extern ImageIO::Image tgaCyanGhostImage;
	extern ImageIO::Image tgaRedGhostImage;
	extern ImageIO::Image tgaPinkGhostImage;
	extern ImageIO::Image tgaOrangeGhostImage;
	extern ImageIO::Image tgaGhostFleeImages[ 2 ];
	extern ImageIO::Image tgaGhostEyesImage;
	extern ImageIO::Image tgaPacManImage;	
	extern ImageIO::Image tgaHud;	
	extern ImageIO::Image tgaMainMenu;
	extern ImageIO::Image tgaStart;
	extern ImageIO::Image tgaExit;
	extern ImageIO::Image tgaGameOver;
	extern ImageIO::Image tgaNextLevel;


	extern FMOD::System *soundSystem;	
	extern FMOD::Sound *soundEffects[ 5 ];
	extern FMOD::Sound *music;
	extern FMOD::Channel *musicChannel;

	typedef enum tagSoundEffect {
		SFX_NEXT_LEVEL = 0,
		SFX_GAME_OVER,
		SFX_BIG_DOT_EATEN,
		SFX_SMALL_DOT_EATEN,
		SFX_GHOST_OR_PACMAN_EATEN
	} SoundEffect;


	// bof Texture Ids
	extern unsigned int nBlockTexture[ 7 ];
	extern unsigned int nBigDotTexture;
	extern unsigned int nSmallDotTexture;
	extern unsigned int nCyanGhostTexture;
	extern unsigned int nRedGhostTexture;
	extern unsigned int nPinkGhostTexture;
	extern unsigned int nOrangeGhostTexture;
	extern unsigned int nGhostFleeTextures[ 2 ];
	extern unsigned int nGhostEyesTexture;
	extern unsigned int nPacManTexture;
	extern unsigned int nMainMenu;
	extern unsigned int nHud;
	extern unsigned int nStart;
	extern unsigned int nExit;
	extern unsigned int nGameOver;
	extern unsigned int nNextLevel;
	// eof Texture Ids

	extern unsigned int nHudDisplayList;

	enum GameState {
		IN_GAME,
		GAME_OVER,
		MAIN_MENU,
		NEXT_LEVEL
	};

	
	extern unsigned int nMainMenuSelection;

	extern unsigned int corners[ 4 ][ 2 ];
	extern GameState state;
	extern std::vector<Object *> gameBoard;
	extern unsigned int nLevel;
	extern unsigned int nDotCount;
	extern unsigned int nNumberOfGhosts;
	extern unsigned int nScore;
	extern int nPlayerLives;
	extern PacMan *pPlayer;
	
	enum { RED_GHOST, ORANGE_GHOST, PINK_GHOST, CYAN_GHOST }; // this defines the indices for the ghosts.
	extern Object *ghosts[ 4 ];

	void loadLevel( const char *filename );
	void unloadLevel( );


	void renderMainMenu( );
	void renderInGame( );
	void renderGameOver( );
	void renderNextLevel( );

	void setGhostSeekPacManMode( int g );
	void updateInGame( );

	void handleMainMenuInput( int key );
	void handleInGameInput( int key );
	void handleGameOverInput( int key );
	void handleNextLevelInput( int key );

	bool isLevelWinCondition( );
	bool isGameWinCondition( );
	bool isGameLoseCondition( );
	void nextLevel( );

	void initializeLevel( );
	void deinitializeLevel( );
} //end of namespace
#endif
